﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Diagnostics;
using System.Threading;
using System.Windows;
using GUI.Custom_Classes;

namespace GUI
{
    public class GuiController
    {
        #region Attributes

        /// <summary>
        /// WMI service watcher registered to watch for processes
        /// </summary>
        private ManagementEventWatcher watcher;

        /// <summary>
        /// Kills watcher process when all processes have exited
        /// </summary>
        private ManagementEventWatcher stopWatch;

        /// <summary>
        /// Background thread to watch for processes
        /// </summary>
        private Thread watchThread;

        /// <summary>
        /// Background thread to watch for processes closing
        /// </summary>
        private Thread stopThread;

        /// <summary>
        /// LEET's process id
        /// </summary>
        private int LEETid;

        /// <summary>
        /// Viewer object from mainTab for managing processes
        /// </summary>
        private ScriptViewer Script_Viewer;

        #endregion

        #region Event Handlers

        

        #endregion

        public GuiController(ScriptViewer sv)
        {
            Script_Viewer = sv;
            Script_Viewer.Unloaded += new RoutedEventHandler(KillWatchers);
            LEETid = Process.GetCurrentProcess().Id;
        }

        /// <summary>
        /// Starts process watcher for test cleanup functionality.
        /// </summary>
        internal void StartWatcher(object sender, RoutedEventArgs e)
        {
            watcher = new ManagementEventWatcher(new WqlEventQuery("__InstanceCreationEvent", new TimeSpan(0, 0, 1), "TargetInstance isa \"Win32_Process\""));
            watcher.EventArrived += new EventArrivedEventHandler(ProcessEvent);
            watcher.Stopped += new StoppedEventHandler(WatcherStopped);
            watchThread = new Thread(new ThreadStart(watcher.Start));
            watchThread.Start();

            stopWatch = new ManagementEventWatcher(new WqlEventQuery("__InstanceDeletionEvent ", new TimeSpan(0, 0, 1), "TargetInstance isa \"Win32_Process\""));
            stopWatch.EventArrived += new EventArrivedEventHandler(ProcessRemoved);
            stopThread = new Thread(new ThreadStart(stopWatch.Start));
            stopThread.Start();
        }

        /// <summary>
        /// Analyzes any new processes that have a main window handle for test cleanup.
        /// </summary>
        private void ProcessEvent(object sender, EventArrivedEventArgs e)
        {
            string proname = (string)((ManagementBaseObject)e.NewEvent["TargetInstance"])["Name"];
            proname = proname.Remove(proname.Length - 4);
            foreach (Process pro in Process.GetProcessesByName(proname))
            {
                if (pro.MainWindowHandle != IntPtr.Zero && pro.Id != LEETid)
                {
                    Script_Viewer.processes.Add(pro);
                    Script_Viewer.pronames.Add(proname);
                }
            }
        }

        /// <summary>
        /// Removes processes from list when they exit
        /// </summary>
        private void ProcessRemoved(object sender, EventArrivedEventArgs e)
        {
            string proname = (string)((ManagementBaseObject)e.NewEvent["TargetInstance"])["Name"];
            proname = proname.Remove(proname.Length - 4);
            int count = 0;
            if (Script_Viewer.pronames.Contains(proname))
            {
                count = Script_Viewer.pronames.IndexOf(proname);
                Script_Viewer.pronames.Remove(proname);
                Script_Viewer.processes.RemoveAt(count);
            }
            if (Script_Viewer.pronames.Count == 0)
            {
                Script_Viewer.processes.Clear();
                WatcherStopped(null, null);
            }
        }

        /// <summary>
        /// Terminates thread for process watcher and disposes process watcher when program terminates.
        /// </summary>
        private void WatcherStopped(object sender, StoppedEventArgs e)
        {
            if (watchThread != null)
            {
                if (watchThread.IsAlive)
                    watchThread.Abort();
                watcher.Dispose();
                if (stopThread.IsAlive)
                    stopThread.Abort();
                stopWatch.Dispose();
            }
        }

        private void KillWatchers(object sender, RoutedEventArgs e)
        {
            WatcherStopped(null, null);
        }
    }
}
